// 注意：
// shared_array 默认是空数组，此时 attribute_t 域是不允许访问的
// shared_array::length() == 0
// shared_array::is_empty() == true
// shared_array::operator==(nullptr) == true
// shared_array::operator=(nullptr) 默认是将该数组指向空数组而不是 nullptr
// 如非必要请勿创建长度 ::length(0) 的数组
// 创建长度为 0 的数组与默认空数组的不同点
// shared_array::operator==(nullptr) == false
#ifndef xpack_utils_shared_array
#define xpack_utils_shared_array
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::utils_shared_array::inc
#include"define/base_type.hpp"
#include"dumb/dummy_type.hpp"
#include"dumb/init_by.hpp"
#include"gc/ref.hpp"
#include"macro/xexport.hpp"
#include"macro/xstruct.hpp"
#include"meta/is_empty_class.hpp"
#pragma pop_macro("xuser")

namespace mixc::utils_shared_array::origin{
    using inc::can_init;
    using inc::init_by;
    using inc::default_init_by;

    template<class type_t, uxx rank = 1, class attribute_t = inc::dummy_type, bool is_binary_aligned_alloc_v = false>
    xstruct(
        xtmpl(shared_array, type_t, rank, attribute_t, is_binary_aligned_alloc_v),
        xpubb(inc::ref_array<
            shared_array<type_t, rank, attribute_t, is_binary_aligned_alloc_v>,
            typename shared_array<type_t, rank - 1, attribute_t, is_binary_aligned_alloc_v>::self_t,
            attribute_t,
            is_binary_aligned_alloc_v
        >)
    )
        using item_t = typename shared_array<type_t, rank - 1, attribute_t, is_binary_aligned_alloc_v>::self_t;
        using self_t = the_t;
        using base_t = inc::ref_array<the_t, item_t, attribute_t, is_binary_aligned_alloc_v>;
        using typename base_t::item_initial_invoke;
        using typename base_t::item_initial_invokex;
        using base_t::operator==;
        using base_t::operator!=;
        using base_t::operator->;
        using base_t::base_t;
    public:
        // 兼容 msvc，shared_array(decltype(nullptr) = nullptr) 可能会被认为默认无参构造函数不存在
        // 导致无法无参初始化
        shared_array(decltype(nullptr)) : base_t() {}
        shared_array()                          = default;
        shared_array(the_t & self)              = default;
        shared_array(the_t && self)             = default;
        the_t & operator=(the_t &)              = default;
        the_t & operator=(the_t &&)             = default;

        operator item_t *() {
            return base_t::operator item_t * ();
        }

        operator item_t const *() const {
            return base_t::operator item_t * ();
        }
    $

    template<class type_t, class attribute_t, bool is_binary_aligned_alloc_v>
    xstruct(
        xspec(shared_array, type_t, 0, attribute_t, is_binary_aligned_alloc_v)
    )
        using self_t = type_t;
    $
}

#endif

xexport_space(mixc::utils_shared_array::origin)